home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_UMINNgopher.idb / usr / freeware / src / gopher_1.12 / gopher / html2.c.z / html2.c
C/C++ Source or Header  |  1997-09-09  |  13KB  |  652 lines

  1. /********************************************************************
  2.  * $Author: drich $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1995/10/03 04:08:09 $
  5.  * $Source: /proj/freeware1.0/gopher1.12/src/gopher/RCS/html2.c,v $
  6.  * $Status: $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: html.c
  14.  * More lame code for html
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: html2.c,v $
  18.  * Revision 1.1  1995/10/03  04:08:09  drich
  19.  * gopher 1.2 check-in
  20.  *
  21.  * Revision 1.1  1992/12/10  23:32:16  lindner
  22.  * gopher 1.1 release
  23.  *
  24.  * Revision 1.1  1992/12/10  06:16:51  lindner
  25.  * Initial revision
  26.  *
  27.  *
  28.  *********************************************************************/
  29.  
  30.  
  31. #include "gopher.h"
  32. #include "Malloc.h"
  33. #include "HTML.h"
  34.  
  35. Ourpager(){ ;}
  36.  
  37. char *process_tag();
  38. static char *parastorage = NULL;
  39. static int  parasize=0;
  40. static int  paraptr=0;
  41.  
  42. static int  HeadingLevel=1;
  43. static int  Linknum =0;
  44.  
  45. /*** State information for the HTML parser, ick  ***/
  46.  
  47. boolean     inANCHOR  = FALSE;
  48. boolean     inXMP     = FALSE;
  49. boolean     inLISTING = FALSE;
  50. boolean     inADDRESS = FALSE;
  51. boolean     inDL      = FALSE;
  52. boolean     inDT      = FALSE;
  53. boolean     inMENU    = FALSE;
  54. boolean     inPLAINTXT= FALSE;
  55. boolean     inLIST    = FALSE;
  56. boolean     inPAREN   = FALSE;
  57. boolean     inH1      = FALSE;
  58. boolean     inHeading = FALSE;
  59. boolean     isIndex   = FALSE;
  60.  
  61. /*** Different Types of justification ***/
  62. #define JUSTIFY_LEFT 1
  63. #define JUSTIFY_CENTER 2
  64. #define JUSTIFY_RIGHT 3
  65.  
  66. /*** Different types of text styles ***/
  67. #define STYLE_NL 1 /** Normal **/
  68. #define STYLE_UL 2 /** Underline **/
  69.  
  70. /** Link delimiters **/
  71. #define START_LINK '\177'
  72. #define END_LINK   '\013'
  73.  
  74. int CurrentLine = 0;
  75. int CurrentLinepos = 0;
  76. extern int COLS;
  77.  
  78. HTMLObj *CurrentHTML;
  79. int anchoroffset = -1;
  80.  
  81. int HTMLfilenum =0;
  82.  
  83. /*
  84.  * Add a character to the paragraph buffer
  85.  */
  86.  
  87. static buffer_ch(ch)
  88.   char ch;
  89. {
  90.      /** check for overflow **/
  91.      if (inANCHOR==FALSE)
  92.       anchoroffset = -1;
  93.  
  94.      if ((inANCHOR == TRUE) && (anchoroffset == -1))
  95.       anchoroffset = paraptr;
  96.  
  97.      if (paraptr == parasize-1) {
  98.       char *temp;
  99.  
  100.       parasize *=2;
  101.       temp = (char*) realloc(parastorage, parasize);
  102.  
  103.       if (temp != parastorage) {
  104.            free(parastorage);
  105.            parastorage = temp;
  106.       }
  107.      }
  108.  
  109.      *(parastorage + paraptr++) = ch;
  110.      *(parastorage + paraptr) = '\0';
  111. }
  112.  
  113.  
  114. /*
  115.  * addch outputs a character to the file
  116.  * It also notes the location of links in the file
  117.  */
  118.  
  119. static add_ch(ch, zefile)
  120.   char ch;
  121.   FILE *zefile;
  122. {
  123.      if (ch == '\t') {
  124.       fprintf(zefile, "        ");
  125.       CurrentLinepos += 8;
  126.      }
  127.      else if (ch == '\n') {
  128.       CurrentLine++;
  129.       CurrentLinepos = 0;
  130.       fputc('\n', zefile);
  131.      }
  132.      else if (ch == START_LINK) {
  133.       HTMLSetLinepos(CurrentHTML, Linknum, CurrentLinepos+1);
  134.       HTMLSetLinenum(CurrentHTML, Linknum, CurrentLine);      
  135.       Linknum++;
  136.       
  137.       CurrentLinepos++;
  138.       fputc('[', zefile);
  139.      }
  140.      else if (ch == END_LINK) {
  141.       CurrentLinepos++;
  142.       fputc(']', zefile);
  143.      }
  144.      else {
  145.       CurrentLinepos++;
  146.       fputc(ch, zefile);
  147.      }
  148. }
  149.  
  150. /*
  151.  * This is the same as add_ch, except it underlines
  152.  */
  153.  
  154. static addul_ch(ch, zefile)
  155.   char ch;
  156.   FILE *zefile;
  157. {
  158.      fputc('_', zefile);
  159.      fputc('\b', zefile);
  160.      add_ch(ch, zefile);
  161. }
  162.  
  163. /*
  164.  * Add a string to the file using add_ch
  165.  */
  166.  
  167. static add_string(cp, zefile)
  168.   FILE *zefile;
  169.   char *cp;
  170. {
  171.      int i;
  172.      
  173.      while (*cp != '\0')
  174.       add_ch(*cp++, zefile);
  175. }
  176.  
  177. /*
  178.  * Add an underlined string
  179.  */
  180.  
  181. static addul_string(cp, zefile)
  182.   FILE *zefile;
  183.   char *cp;
  184. {
  185.      int i;
  186.      
  187.      while (*cp != '\0')
  188.       addul_ch(*cp++, zefile);
  189. }
  190.  
  191. /*
  192.  * Flush the paragraph buffer
  193.  */
  194. flush_null(zefile)
  195.   FILE *zefile;
  196. {
  197.      paraptr = 0;
  198. }
  199.  
  200. /*
  201.  * Output the buffer as is
  202.  */
  203.  
  204. flush_raw(zefile)
  205.   FILE *zefile;
  206. {
  207.      if (paraptr == 0)
  208.       return;
  209.  
  210.      *(parastorage +paraptr) = '\0';
  211.  
  212.      if (inXMP == TRUE || inLISTING==TRUE) {
  213.       add_string(parastorage, zefile);
  214.       paraptr = 0;
  215.       return;
  216.      }
  217.  
  218.      add_ch('\n', zefile);
  219.      
  220. }
  221.  
  222.  
  223. char *
  224. strip_crap_begin(cp)
  225.   char *cp;
  226. {
  227.      while (*cp == ' ' || *cp == '\n') {
  228.       cp++;
  229.      }
  230.      return(cp);
  231. }
  232.  
  233.  
  234.  
  235.  
  236.  
  237. /*
  238.  * Add a generalized paragraph.  Does word wrapping, justification,
  239.  * leading space, total indentation level, bullets, and underlining
  240.  */
  241. static flush_it(zefile, leading, indent, bullet, justify, style)
  242.   FILE *zefile;
  243.   int leading;
  244.   int indent;
  245.   char *bullet;
  246.   int justify;
  247.   int style;
  248. {
  249.      char *lastspace = NULL;
  250.      register char *cp;
  251.      char *beginline = parastorage;
  252.      int i;
  253.      int testlinepos=0;
  254.      
  255.      while (CurrentLinepos < indent) {
  256.       add_ch(' ', zefile);
  257.      }            
  258.      
  259.      /** Add leading space **/
  260.      while (leading-- != 0)
  261.       add_ch(' ', zefile);
  262.      
  263.      /** Add bullet space **/
  264.      if (bullet != NULL)
  265.       add_string(bullet, zefile);
  266.  
  267.      testlinepos = CurrentLinepos;
  268.      cp = beginline = strip_crap_begin(parastorage);
  269.  
  270.      for (; cp < parastorage+paraptr; cp++, testlinepos++) {
  271.  
  272.       if (*cp == '\n')
  273.            *cp = ' ';
  274.       if (*cp == ' ')
  275.            lastspace = cp;
  276.       
  277.       if (testlinepos == COLS-1) {
  278.            if (lastspace == NULL)  {  /** Big long line, chop it. **/
  279.             char tempch = *cp;
  280.  
  281.             *cp = '\0';
  282.             if (style == STYLE_UL)
  283.              addul_string(beginline, zefile);
  284.             else
  285.              add_string(beginline, zefile);
  286.             add_ch('\n', zefile);
  287.             *cp = tempch;
  288.             cp = strip_crap_begin(cp);
  289.             beginline = cp;
  290.            } else {
  291.             *lastspace = '\0';
  292.             
  293.             /** Justify here **/
  294.             if (justify == JUSTIFY_RIGHT) {
  295.              for (i=CurrentLinepos; i<(COLS -(lastspace-beginline)); i++)
  296.                   add_ch(' ', zefile);
  297.             }
  298.             if (style == STYLE_UL)
  299.              addul_string(beginline, zefile);
  300.             else
  301.              add_string(beginline, zefile);
  302.  
  303.              add_ch('\n', zefile);
  304.             cp = strip_crap_begin(lastspace+1);
  305.             beginline = cp;
  306.            }
  307.  
  308.            lastspace = NULL;
  309.            
  310.            while (CurrentLinepos < indent) {
  311.             add_ch(' ', zefile);
  312.            }
  313.  
  314.            if (bullet != NULL) {
  315.             for (i=0; i <strlen(bullet); i++)
  316.              add_ch(' ', zefile);
  317.            }
  318.            
  319.            testlinepos = CurrentLinepos;
  320.       }
  321.      }
  322.      if (justify == JUSTIFY_RIGHT) {
  323.       while (CurrentLinepos < (COLS-strlen(beginline)-1))
  324.            add_ch(' ', zefile);
  325.      } else if (justify == JUSTIFY_CENTER) {
  326.       while (CurrentLinepos < ((COLS-strlen(beginline)-1)/2))
  327.            add_ch(' ', zefile);
  328.      }
  329.      if (style == STYLE_UL)
  330.       addul_string(beginline, zefile);
  331.      else
  332.       add_string(beginline, zefile);
  333.  
  334.      if (inDT == FALSE) {
  335.       add_ch('\n', zefile);
  336.       if (inADDRESS == FALSE)
  337.            add_ch('\n', zefile);
  338.      }
  339.  
  340.      paraptr = 0;
  341. }
  342.  
  343. /*
  344.  * Output the paragraph  take note of our state and add different styles.
  345.  */
  346.  
  347. static flush_paragraph(zefile)
  348.   FILE *zefile;
  349. {
  350.      char *cp;
  351.  
  352.      if (paraptr == 0)
  353.       return;
  354.      
  355.      /*** If it's a bunch of '\n''s skip it... ***/
  356.      for (cp = parastorage; (*cp == '\n'); cp++)
  357.       ;
  358.      if (*cp == '\0')
  359.       return;
  360.  
  361.      if (inADDRESS==TRUE)
  362.       flush_it(zefile, 0, HeadingLevel*3, NULL, JUSTIFY_RIGHT, STYLE_NL);
  363.      else if (inDL==TRUE) {
  364.       if (inDT)
  365.            flush_it(zefile, 0, HeadingLevel*3, NULL, JUSTIFY_LEFT, STYLE_UL);
  366.       else
  367.            flush_it(zefile, 1, (HeadingLevel+1)*3, NULL, JUSTIFY_LEFT, STYLE_NL);
  368.      }
  369.      else if (inLIST==TRUE) {
  370.       flush_it(zefile, 0, HeadingLevel*3, "* ", JUSTIFY_LEFT,STYLE_NL);
  371.      }
  372.      else if (inH1 == TRUE)
  373.       flush_it(zefile, 0, 0, NULL, JUSTIFY_CENTER, STYLE_UL);
  374.      else if (inHeading == TRUE)
  375.       flush_it(zefile, 0, (HeadingLevel-1)*3, NULL, JUSTIFY_LEFT, STYLE_UL);
  376.      else {
  377.       flush_it(zefile, 3, HeadingLevel*3, NULL, JUSTIFY_LEFT, STYLE_NL);
  378.      }
  379. }
  380.  
  381. HTMLfromNet(html, sockfd)
  382.   HTMLObj *html;
  383.   int sockfd;
  384. {
  385.      ;
  386. }
  387.  
  388. do_html(ZeGopher)
  389.   GopherObj *ZeGopher;
  390. {
  391.      FILE *tmpfile;
  392.      char tmpfilename[256];
  393.      char inputline[512];
  394.      char outputline[512];
  395.      char sTmp[5], *cp;
  396.      int sockfd, iLength;
  397.  
  398.      if (parastorage == NULL) {
  399.       parasize = 4096;
  400.       paraptr = 0;
  401.       parastorage = (char *) malloc(parasize);
  402.       bzero(parastorage, 4096);
  403.      }
  404.  
  405.      CurrentHTML = HTMLnew(32);
  406.  
  407.      if ((sockfd = GSconnect(ZeGopher)) <0) {
  408.       check_sock(sockfd, GSgetHost(ZeGopher));
  409.       return;
  410.      }
  411.  
  412.      /** Send out the request **/
  413.  
  414.      writestring(sockfd, GSgetPath(ZeGopher));
  415.      writestring(sockfd, "\r\n");
  416.  
  417.      /** Open a temporary file **/
  418.  
  419.      sprintf(tmpfilename, "/tmp/gopherhtml.%d.%d",getpid(),HTMLfilenum++);
  420.  
  421.      if ((tmpfile = fopen(tmpfilename, "w")) == NULL)
  422.       fprintf(stderr, "Couldn't make a tmp file!\n"), exit(-1);
  423.  
  424.      for(;;) {
  425.  
  426.       iLength = readline(sockfd, inputline, 512);
  427.       outputline[0] = '\0';
  428.       if (iLength == 0)
  429.            break;
  430.  
  431.       ZapCRLF(inputline);
  432.  
  433.       for (cp=inputline; *cp != '\0'; cp++) {
  434.  
  435.            if (*cp == '<') { /** Start of tag? **/
  436.             char *cp2;
  437.  
  438.             cp = process_tag(cp, tmpfile);
  439.            } 
  440.            else
  441.             buffer_ch(*cp);
  442.       } 
  443.       buffer_ch('\n');
  444.      }
  445.  
  446.      flush_paragraph(tmpfile);
  447.  
  448.      if (isIndex)
  449.       ;/*     add_index_entry(zefile);*/
  450.  
  451.      (void)fclose(tmpfile);
  452.  
  453.      
  454. /*     display_file(tmpfilename, GSgetTitle(ZeGopher));*/
  455.  
  456.      CURexit(CursesScreen);
  457.  
  458.      HTML_pager(tmpfilename, CurrentHTML);
  459.  
  460.      /** Good little clients clean up after themselves..**/
  461.  
  462.      if (unlink(tmpfilename)!=0)
  463.       fprintf(stderr, "Couldn't unlink!!!\n"), exit(-1);
  464.  
  465.      CURenter(CursesScreen);
  466. }
  467.  
  468.  
  469.  
  470. char *
  471. process_tag(cp, tmpfile)
  472.   char *cp;
  473.   FILE *tmpfile;
  474. {
  475.      char *cp2;
  476.      char *endtag;
  477.      static GopherObj *Anchorgs=NULL;
  478.  
  479.      
  480.      for (cp2 = cp+1;
  481.       *cp2 != '>' && *cp2 != '<' && *cp2 != '\0';
  482.       cp2++)
  483.       if (*cp2 == ' ')
  484.            endtag = cp2;
  485.      
  486.      if (endtag==NULL) endtag=cp2;
  487.  
  488.      if (*cp2 != '>')   /** Not a tag **/
  489.       return(cp);
  490.  
  491.      /** It's a tag.. */
  492.  
  493.  
  494.      /*** Check for these cases first, they're weird ***/
  495.  
  496.      if (inXMP == TRUE) {
  497.       if (strncasecmp(cp, "</XMP",5)==0) {
  498.            flush_raw(tmpfile);
  499.            inXMP = FALSE;
  500.            return(cp2);
  501.       }
  502.       inPAREN = TRUE;
  503.       buffer_ch(*cp);
  504.       return(cp);
  505.      }
  506.      else if (inLISTING == TRUE) {
  507.       if (strncasecmp(cp, "</LISTING",5)==0) {
  508.            flush_raw(tmpfile);
  509.            inLISTING = FALSE;
  510.             return(cp2);
  511.       }
  512.       inPAREN = TRUE;
  513.       buffer_ch(*cp);
  514.       return(cp);
  515.      }
  516.  
  517.  
  518.  
  519.      /** Check for tags that are embedded in paragraphs **/
  520.      if (strncasecmp(cp, "<A ", 3)==0) {
  521.       char *href;
  522.  
  523.       href = strstr(cp, "HREF=");
  524.       if (href == NULL)
  525.            return(cp2);
  526.            
  527.       href += 5;
  528.       if (Anchorgs == NULL)
  529.            Anchorgs = GSnew();
  530.       else
  531.            GSinit(Anchorgs);
  532.  
  533.       GSfromHREF(Anchorgs, href);
  534.  
  535.       /** An anchor link **/
  536.       buffer_ch(START_LINK);
  537.            
  538.       inANCHOR = TRUE;
  539.       return(cp2);
  540.  
  541.      }
  542.      else if (strncasecmp(cp, "</A>", 4)==0) {
  543.       if (inANCHOR == TRUE) {
  544.            GSsetTitle(Anchorgs, parastorage+anchoroffset); /** Ick **/
  545.            buffer_ch(END_LINK);
  546.            buffer_ch(' ');
  547.            inANCHOR = FALSE;
  548.       }
  549.       HTMLaddLink(CurrentHTML, Anchorgs, 42,42);
  550.  
  551.       return(cp2);
  552.      }
  553.  
  554.      /** Okay, anything else ends a paragraph, if we're in it... **/
  555.  
  556.      if (inPAREN == TRUE) {
  557.       flush_paragraph(tmpfile);
  558.       inPAREN = FALSE;
  559.      }
  560.  
  561.      /*** Assume that we're in a paragraph ***/
  562.      inPAREN = TRUE;
  563.  
  564.      /** Any other tag is the start of something new **/
  565.      
  566.      if (strncasecmp(cp, "<P", 2)==0) {
  567.       inPAREN = TRUE;
  568.      }
  569.  
  570.      else if (strncasecmp(cp, "<ADDRESS", 8)==0) {
  571.       inADDRESS =TRUE;
  572.       add_ch('\n', tmpfile);
  573.      }
  574.  
  575.      else if (strncasecmp(cp, "</ADDRESS",9)==0) {
  576.       inADDRESS = FALSE;
  577.      }
  578.      
  579.      else if (strncasecmp(cp, "<TITLE",6)==0) {
  580.       inPAREN = FALSE;
  581.      }
  582.      else if (strncasecmp(cp, "</TITLE",7)==0) {
  583.       flush_null(tmpfile);
  584.      }
  585.      else if (strncasecmp(cp, "<H1", 3) ==0) {
  586.       inH1 = TRUE;
  587.      }
  588.      else if (strncasecmp(cp, "<H",2) ==0) {
  589.       HeadingLevel = *(cp+2) - '0' - 1;
  590.       inHeading = TRUE;
  591.      }
  592.      else if (strncasecmp(cp, "</H1", 4) ==0) {
  593.       inH1=FALSE;
  594.      }
  595.      else if (strncasecmp(cp, "</H", 3) ==0) {
  596.       inHeading = FALSE;
  597.      }
  598.      else if (strncasecmp(cp, "<XMP", 4)==0) {
  599.       add_ch('\n',tmpfile);
  600.       inXMP = TRUE;
  601.       inPAREN = FALSE;
  602.      }
  603.      else if (strncasecmp(cp, "<LISTING",7)==0) {
  604.       add_ch('\n',tmpfile);
  605.       inLISTING = TRUE;
  606.       inPAREN = FALSE;
  607.      }
  608.      else if (strncasecmp(cp, "<DL",3)==0) {
  609.       inDL = TRUE;
  610.       inPAREN = FALSE;
  611.      }
  612.      else if (strncasecmp(cp, "<DD", 3)==0) {
  613.       inPAREN = TRUE;
  614.       inDT = FALSE;
  615.  
  616.       /*flush_term(tmpfile);*/
  617.      }
  618.  
  619.      else if (strncasecmp(cp, "<DT", 3)==0) {
  620.       inDT = TRUE;
  621.      }
  622.      
  623.      else if ( strncasecmp(cp, "</DL",4)==0) {
  624.       inDL = FALSE;
  625.      }
  626.      
  627.      else if (strncasecmp(cp, "<UL",3)==0) {
  628.       inLIST = TRUE;
  629.      }
  630.      else if (strncasecmp(cp, "<MENU",5)==0) {
  631.       inMENU =TRUE;
  632.      }
  633.      else if (strncasecmp(cp, "</MENU",6)==0) {
  634.       inMENU=FALSE;
  635.      }
  636.      else if (strncasecmp(cp, "<LI", 3)==0) {
  637.       ;
  638.      }
  639.      else if (strncasecmp(cp, "</UL", 4)==0) {
  640.       inLIST = FALSE;
  641.      }
  642.  
  643.      else if (strncasecmp(cp, "</ISINDEX", 9)==0) {
  644.       isIndex = TRUE;
  645.      }
  646.      
  647.      else if (strncasecmp(cp, "<PLAINTEXT", 10)==0) {
  648.       inPLAINTXT = TRUE;
  649.      }
  650.      return(cp2);
  651. }
  652.